package com.cskaoyan.javse.oop3._0abstract._3exercise;

/**
 * @description: 小练习
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * 小试牛刀
 * 我们正在开发一套员工管理系统，需要对公司内部存在的员工进行管理
 * 公司将员工分为三类，普通员工负责杂项工作，程序员负责技术开发，经理负责统筹规划
 *
 * 普通员工包含3个属性：姓名、工号以及工资，行为是工作
 * 程序员包含3个属性：姓名、工号以及工资，行为是工作和加班（overtime work）
 * 经理包含4个属性：姓名、工号、工资以及奖金（bonus），行为是工作
 * 请使用所学的知识设计该员工系统
 * 怎么设计?
 * 假如不定义抽象类,直接把普通员工作为父类,可以不可以? 在本案例中是可以的,但是从程序的长远发展来看,是不合适的
 * 原因在于:
 *      1.程序中会存在一个对象,叫"普通员工",假如有一天,更改了需求,普通员工有了新的行为,新的属性,这些修改都会体现到经理类和程序员类,这是不好的,所以在设计父类时,尽量能够找到不需要创建对象的,这样才可以完全的抽离它们的共性
 *      2.如果直接用普通员工作为父类,它肯定是一个普通类,那么就没有抽象方法了,就不能限制子类必须重写某个方法
 *
 * 以上,在这个案例中,应该设计一个抽象的父类,AbstractStaff
 *
 * 要求类中提供必要的方法进行属性访问（description）
 * 需要写一个方法getDescription();
 *
 */
public class Demo {
    public static void main(String[] args) {
        AbstractStaff as;
        as = new GeneralStaff("李四", 2, 5000);
        as.work();
        System.out.println(as.getDescription());

        as = new Coder("麻子", 3, 8000);
        as.work();
        //程序员额外的行为:加班
        if (as instanceof Coder) {
            Coder c = (Coder) as;
            c.overtimeWork();
        }
        System.out.println(as.getDescription());

        as = new Manager("张三", 1, 10000, 100000);
        as.work();
        if (as instanceof Manager) {
            Manager m = (Manager) as;
            System.out.println(m.bonus);
        }
        System.out.println(as.getDescription());
    }
}

//定义抽象的员工类
abstract class AbstractStaff {
    //属性
    String name;
    int id;
    double salary;

    //行为
    public abstract void work();

    //构造方法
    public AbstractStaff() {
    }

    public AbstractStaff(String name, int id, double salary) {
        this.name = name;
        this.id = id;
        this.salary = salary;
    }

    //定义成员方法,作为子类的默认实现,子类可以选择调用,也可以选择重写
    public String getDescription() {
        return "名字为" + this.name + "的" + id + "号员工,他的工资是" + salary;
    }

}

//定义具体的子类
class GeneralStaff extends AbstractStaff {
    @Override
    public void work() {
        System.out.println("普通员工负责杂项工作");
    }

    public GeneralStaff(String name, int id, double salary) {
        super(name, id, salary);
    }

    public GeneralStaff() {
    }
}

class Coder extends AbstractStaff {
    @Override
    public void work() {
        System.out.println("程序员负责技术开发");
    }

    //额外的行为
    public void overtimeWork() {
        System.out.println("加班996");
    }

    public Coder() {
    }

    public Coder(String name, int id, double salary) {
        super(name, id, salary);
    }
}

class Manager extends AbstractStaff {
    //额外的属性
    double bonus;

    @Override
    public void work() {
        System.out.println("经理负责统筹规划");
    }

    public Manager() {
    }

    public Manager(String name, int id, double salary, double bonus) {
        super(name, id, salary);
        this.bonus = bonus;
    }

    //经理类需要重写抽象类中的方法

    @Override
    public String getDescription() {
        return "名字为" + this.name + "的" + id + "号员工,他的工资是" + (salary + bonus);
    }
}
